package com.htgd.gardenexpo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.htgd.gardenexpo.dao.*;
import com.htgd.gardenexpo.dto.GeConCompetitionSportsDTO;
import com.htgd.gardenexpo.entity.*;
import com.htgd.gardenexpo.page.CompetitionSportsQuery;
import com.htgd.gardenexpo.page.MarathonListQuery;
import com.htgd.gardenexpo.page.PageBase;
import com.htgd.gardenexpo.service.*;
import com.htgd.gardenexpo.utils.GaoDeUtils;
import com.htgd.gardenexpo.utils.HttpRequest;
import com.htgd.gardenexpo.utils.TokenUtil;
import com.htgd.gardenexpo.utils.UUIDUtils;
import com.htgd.gardenexpo.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 * 赛事运动 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-09-21
 */
@Service
public class GeConCompetitionSportsServiceImpl extends ServiceImpl<GeConCompetitionSportsMapper, GeConCompetitionSports> implements GeConCompetitionSportsService {

    @Autowired
    private GeConCompetitionGroupMapper geConCompetitionGroupMapper;
    @Autowired
    private GeConCompetitionSportsMapper geConCompetitionSportsMapper;

    @Autowired
    private GeBaseDictService geBaseDictService;

    @Autowired
    private GeConUserCompeteMapper geConUserCompeteMapper;

    @Autowired
    private GeConCompetitionPrizeMapper geConCompetitionPrizeMapper;

    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private DeviceService deviceService;

    @Value("${device.tenant_id}")
    private String tenantId;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String DELAYED_MESSAGES_ZSET = "delayed:messages";

    @Autowired
    private DelayMessageMapper delayMessageMapper;

    @Autowired
    private GeConLineMapper geConLineMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private WxUserCollectService wxUserCollectService;

    @Autowired
    private GeConSocialTopicsMapper geConSocialTopicsMapper;

    @Autowired
    private WxUserDao wxUserDao;

    @Autowired
    private GaoDeUtils gaoDeUtils;

    @Autowired
    private IGeConWeatherService geConWeatherService;


    @Value("${local.url}")
    public String local_url;

    @Transactional
    @Override
    public CommonResult insert(GeConCompetitionSportsDTO geConCompetitionSportsDTO){
        //判断时间合理性
        if(geConCompetitionSportsDTO.getEndDate().isAfter(geConCompetitionSportsDTO.getStartTime())){
            return CommonResult.error("报名结束时间不能在活动开始时间之后");
        }
        //话题名字不能重复
        boolean exists = geConSocialTopicsMapper.exists(new LambdaQueryWrapper<GeConSocialTopics>().eq(GeConSocialTopics::getName, geConCompetitionSportsDTO.getName()));
        if(exists){
            return CommonResult.error("该名字已被话题占用，请重新命名");
        }
        //插入数据
        GeConCompetitionSports geConCompetitionSports = new GeConCompetitionSports();
        BeanUtils.copyProperties(geConCompetitionSportsDTO, geConCompetitionSports);
        geConCompetitionSports.setStatus(4);
        geConCompetitionSports.setActive("0");
        geConCompetitionSports.setGroup(geConCompetitionSportsDTO.getGroups().size());
        geConCompetitionSportsMapper.insert(geConCompetitionSports);
        //插入组别
        for (GeConCompetitionGroup group : geConCompetitionSportsDTO.getGroups()) {
            GeConCompetitionGroup geConCompetitionGroup = new GeConCompetitionGroup();
            geConCompetitionGroup.setName(group.getName());
            geConCompetitionGroup.setNum(group.getNum());
            geConCompetitionGroup.setSportId(geConCompetitionSports.getId());
            geConCompetitionGroupMapper.insert(geConCompetitionGroup);
        }
        return CommonResult.success("添加成功");
    }

    @Transactional
    @Override
    public CommonResult delete(String id) {
        GeConCompetitionSports geConCompetitionSports = new GeConCompetitionSports();
        geConCompetitionSports.setId(id);
        geConCompetitionSports.setIsDelete(1);
        updateById(geConCompetitionSports);
        return CommonResult.success("删除成功");
    }

    @Override
    public PageInfo<GeConCompetitionSportsVO> pageList(CompetitionSportsQuery competitionSportsQuery) {
        PageHelper.startPage(competitionSportsQuery.getPageNum(), competitionSportsQuery.getPageSize());
        List<GeConCompetitionSportsVO> list= geConCompetitionSportsMapper.pageList(competitionSportsQuery);
        for (GeConCompetitionSportsVO geConCompetitionSportsVO : list) {
            //获取字典值
            if(geConCompetitionSportsVO.getStatus()!=null){
                geConCompetitionSportsVO.setStatusText(geBaseDictService.getStatusText(String.valueOf(geConCompetitionSportsVO.getStatus())));
            }

            if(geConCompetitionSportsVO.getIsTop()!=null){
                geConCompetitionSportsVO.setIsTopText(geBaseDictService.getTopText(String.valueOf(geConCompetitionSportsVO.getIsTop())));
            }

            if(geConCompetitionSportsVO.getType()!=null){//类型
                geConCompetitionSportsVO.setTypeText(geBaseDictService.getTextByCodeAndValue("type_competition",geConCompetitionSportsVO.getType()));
            }
            //组别
            QueryWrapper<GeConCompetitionGroup> geConCompetitionGroupQueryWrapper = new QueryWrapper<>();
            geConCompetitionGroupQueryWrapper.eq("sport_id",geConCompetitionSportsVO.getId());
            List<GeConCompetitionGroup> geConCompetitionGroups = geConCompetitionGroupMapper.selectList(geConCompetitionGroupQueryWrapper);
            geConCompetitionSportsVO.setGroups(geConCompetitionGroups);

            //报名人数
            Long num = geConUserCompeteMapper.selectCount(
                    new LambdaQueryWrapper<GeConUserCompete>()
                            .eq(GeConUserCompete::getMotionId, geConCompetitionSportsVO.getId())
                            .eq(GeConUserCompete::getSportsType,"1")
                            .eq(GeConUserCompete::getStatus, "1"));
            geConCompetitionSportsVO.setNum(num);
        }
        return new PageInfo<>(list);
    }

    @Override
    public GeConCompetitionSportsVO getDetailsById(String id, HttpServletRequest request) {
        GeConCompetitionSportsVO geConCompetitionSportsVO = new GeConCompetitionSportsVO();
        GeConCompetitionSports geConCompetitionSports = geConCompetitionSportsMapper.selectById(id);
        BeanUtils.copyProperties(geConCompetitionSports,geConCompetitionSportsVO);
        //获取openId
        String accessToken = request.getHeader("Access_token");
        String openId = TokenUtil.getUsernameFromToken(accessToken);
        //当前时间
        LocalDateTime now = LocalDateTime.now();
        geConCompetitionSportsVO.setNow(now);
        //赛事时间
        geConCompetitionSportsVO.setStart(geConCompetitionSportsVO.getStartTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        geConCompetitionSportsVO.setEnd(geConCompetitionSportsVO.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        //获取字典值
        if(geConCompetitionSportsVO.getStatus()!=null){//审批状态
            geConCompetitionSportsVO.setStatusText(geBaseDictService.getStatusText(String.valueOf(geConCompetitionSportsVO.getStatus())));
        }
        if(geConCompetitionSportsVO.getIsTop()!=null){//是否置顶
            geConCompetitionSportsVO.setIsTopText(geBaseDictService.getTopText(String.valueOf(geConCompetitionSportsVO.getIsTop())));
        }
        if(geConCompetitionSportsVO.getType()!=null){//赛事类型
            geConCompetitionSportsVO.setTypeText(geBaseDictService.getTextByCodeAndValue("type_competition",geConCompetitionSportsVO.getType()));
        }
        if(geConCompetitionSportsVO.getActive()!=null){//活动状态(0未开始，1进行中，2结束)
            geConCompetitionSportsVO.setActiveText(geBaseDictService.getTextByCodeAndValue("status_competition",geConCompetitionSportsVO.getActive()));
        }
        //根据openID 获取状态
        if(Objects.nonNull(openId)&& !openId.equals("")){
            GeConUserCompete geConUserCompete = geConUserCompeteMapper.selectOne(new LambdaQueryWrapper<GeConUserCompete>()
                    .eq(GeConUserCompete::getStatus, "1")
                    .eq(GeConUserCompete::getOpenId, openId)
                    .eq(GeConUserCompete::getMotionId, id)
                    .eq(GeConUserCompete::getSportsType, "1"));
            //报名id
            if(geConUserCompete!=null){
                geConCompetitionSportsVO.setEnrollId(geConUserCompete.getId());
            }

            //报名状态
            if(geConUserCompete!=null&&"1".equals(geConUserCompete.getStatus())){
                geConCompetitionSportsVO.setSignUp("1");
                geConCompetitionSportsVO.setSignUpText("已报名");
            }else{
                geConCompetitionSportsVO.setSignUp("0");
                geConCompetitionSportsVO.setSignUpText("未报名");
            }

            //绑定状态
            if("1".equals(geConCompetitionSports.getBinding())){//手环
                if(geConUserCompete!=null&&geConUserCompete.getBracelet()!=null){
                    geConCompetitionSportsVO.setBindingStatus("1");
                    geConCompetitionSportsVO.setBindingStatusText("已绑定");
                }else{
                    geConCompetitionSportsVO.setBindingStatus("0");
                    geConCompetitionSportsVO.setBindingStatusText("未绑定");
                }
            }else {//人脸
                WxUser wxUser = wxUserDao.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenId, openId));
                if(wxUser!=null && "1".equals(wxUser.getFace())){
                    geConCompetitionSportsVO.setBindingStatus("1");
                    geConCompetitionSportsVO.setBindingStatusText("已绑定");
                }else {
                    geConCompetitionSportsVO.setBindingStatus("0");
                    geConCompetitionSportsVO.setBindingStatusText("未绑定");
                }
            }

        }
        //热门
        if(Objects.equals(geConCompetitionSportsVO.getHot(),"0")) geConCompetitionSportsVO.setHotText("普通");
        if(Objects.equals(geConCompetitionSportsVO.getHot(),"1")) geConCompetitionSportsVO.setHotText("热门");
        //组别
        List<GeConCompetitionGroup> groups = geConCompetitionGroupMapper.selectList(new LambdaQueryWrapper<GeConCompetitionGroup>().eq(GeConCompetitionGroup::getSportId,id));
        for(GeConCompetitionGroup item:groups) {
            Long count = geConUserCompeteMapper.selectCount(new LambdaQueryWrapper<GeConUserCompete>()
                    .eq(GeConUserCompete::getStatus, "1")
                    .eq(GeConUserCompete::getSportsType, "1")
                    .eq(GeConUserCompete::getGroupId, item.getId()));
            item.setLeaveNum(item.getNum().longValue() - count);
            item.setSignUpNum(count);
        }
        geConCompetitionSportsVO.setGroups(groups);
        geConCompetitionSportsVO.setGroupName(groups.stream().map(x->x.getName()).collect(Collectors.joining(" ")));
        //报名人头像
        List<String> openIds = geConUserCompeteMapper.selectList(new LambdaQueryWrapper<GeConUserCompete>()
                .eq(GeConUserCompete::getSportsType, "1")
                .eq(GeConUserCompete::getMotionId,id)
                .eq(GeConUserCompete::getStatus,"1")
                .orderByDesc(GeConUserCompete::getCreateTime)
                .last("limit 5")).stream().map(x->x.getOpenId()).collect(Collectors.toList());
        if(!openIds.isEmpty()){
            List<String> imageUrls = openIds.stream()
                    .map(item -> {
                        // 查找 WxUser 对象
                        WxUser user = wxUserService.getOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenId, item));
                        // 如果找到了用户，则使用用户的 URL；如果找不到，则使用默认 URL
                        return Optional.ofNullable(user)
                                .map(u -> Optional.ofNullable(u.getUrl()).orElse(local_url + "head/moren.jpeg"))
                                .orElse(local_url + "head/moren.jpeg");
                    })
                    .collect(Collectors.toList());

            geConCompetitionSportsVO.setImages(imageUrls);
        }else{
            geConCompetitionSportsVO.setImages(new ArrayList<>());
        }
        //已报名人数
        geConCompetitionSportsVO.setNum(geConUserCompeteMapper.selectCount(
                new LambdaQueryWrapper<GeConUserCompete>()
                        .eq(GeConUserCompete::getSportsType, "1")
                        .eq(GeConUserCompete::getMotionId,id)
                        .eq(GeConUserCompete::getStatus,"1")));

        //天气
        JSONObject weather = geConWeatherService.getWeather();
        if(weather!=null){
            geConCompetitionSportsVO.setWeather(weather);
        }

        //浏览量加1
        lambdaUpdate().eq(GeConCompetitionSports::getId,id)
                .setSql("hit = hit + 1")
                .update();

        return geConCompetitionSportsVO;
    }

    @Transactional
    @Override
    public CommonResult edit(GeConCompetitionSportsDTO geConCompetitionSportsDTO) {
        //判断时间合理性
        if(geConCompetitionSportsDTO.getEndDate().isAfter(geConCompetitionSportsDTO.getStartTime())){
            return CommonResult.error("报名结束时间不能在活动开始时间之后");
        }
        //修改数据
        GeConCompetitionSports geConCompetitionSports = new GeConCompetitionSports();
        BeanUtils.copyProperties(geConCompetitionSportsDTO, geConCompetitionSports);
        geConCompetitionSports.setStatus(4);
        geConCompetitionSports.setActive("0");
        geConCompetitionSports.setGroup(geConCompetitionSportsDTO.getGroups().size());
        geConCompetitionSportsMapper.updateById(geConCompetitionSports);
        //删除组别
        QueryWrapper<GeConCompetitionGroup> geConCompetitionGroupQueryWrapper = new QueryWrapper<>();
        geConCompetitionGroupQueryWrapper.eq("sport_id", geConCompetitionSportsDTO.getId());
        geConCompetitionGroupMapper.delete(geConCompetitionGroupQueryWrapper);
        //重新插入组别
        for (GeConCompetitionGroup group : geConCompetitionSportsDTO.getGroups()) {
            GeConCompetitionGroup geConCompetitionGroup = new GeConCompetitionGroup();
            geConCompetitionGroup.setName(group.getName());
            geConCompetitionGroup.setNum(group.getNum());
            geConCompetitionGroup.setSportId(geConCompetitionSports.getId());
            geConCompetitionGroupMapper.insert(geConCompetitionGroup);
        }
        return CommonResult.success("成功");
    }

    @Transactional
    @Override
    public CommonResult review(GeConCompetitionSports geConCompetitionSports) {
        GeConCompetitionSports geConCompetitionSports2 = geConCompetitionSportsMapper.selectById(geConCompetitionSports.getId());

        //发布
        if(Objects.equals(geConCompetitionSports.getStatus(),3)){
            if(LocalDateTime.now().isBefore(geConCompetitionSports2.getStartTime())){
                updateById(geConCompetitionSports);
                DelayMessage delayMessage = new DelayMessage();
                delayMessage.setId(UUIDUtils.generateUniqueString());
                delayMessage.setType("1");
                delayMessage.setContent(JSON.toJSONString(geConCompetitionSports2));
                delayMessage.setExpireTime(geConCompetitionSports2.getStartTime().toEpochSecond(ZoneOffset.of("+8")) * 1000);
                delayMessage.setStatus("1");
                redisTemplate.opsForZSet().add(DELAYED_MESSAGES_ZSET, JSON.toJSONString(delayMessage),
                        geConCompetitionSports2.getStartTime().toEpochSecond(ZoneOffset.of("+8")) * 1000);
                delayMessageMapper.insert(delayMessage);
                DelayMessage delayMessage2 = new DelayMessage();
                delayMessage2.setId(UUIDUtils.generateUniqueString());
                delayMessage2.setType("1");
                delayMessage2.setContent(JSON.toJSONString(geConCompetitionSports2));
                delayMessage2.setExpireTime(geConCompetitionSports2.getEndTime().toEpochSecond(ZoneOffset.of("+8")) * 1000);
                delayMessage2.setStatus("2");
                redisTemplate.opsForZSet().add(DELAYED_MESSAGES_ZSET, JSON.toJSONString(delayMessage2),
                        geConCompetitionSports2.getEndTime().toEpochSecond(ZoneOffset.of("+8")) * 1000);
                delayMessageMapper.insert(delayMessage2);

                //插入赛事话题
                GeConSocialTopics geConSocialTopics = new GeConSocialTopics();
                geConSocialTopics.setName(geConCompetitionSports2.getName());
                geConSocialTopics.setType("1");
                geConSocialTopics.setStatus("1");
                geConSocialTopicsMapper.insert(geConSocialTopics);
            }else{
                return CommonResult.error("当前时间晚于活动开始时间，不允许发布");
            }
        }else{
            updateById(geConCompetitionSports);
        }
        return CommonResult.success("成功");
    }

    @Override
    public CommonResult<List<CompetitionSportsNumsVO>> getEntryNums(Integer pageNum, Integer pageSize, String startTime, String endTime, String startDate, String endDate, String type, String orderBy) {

        PageHelper.startPage(pageNum,pageSize);
        List<CompetitionSportsNumsVO> competitionSportsNumsVOS = geConCompetitionSportsMapper.getEntryNums(startTime,endTime,startDate,endDate,type,orderBy);

        return CommonResult.success("查询成功",competitionSportsNumsVOS);
    }

    @Override
    public PageInfo<MarathonListVO> marathonList(MarathonListQuery marathonListQuery) {
        PageHelper.startPage(marathonListQuery.getPageNum(),marathonListQuery.getPageSize());
        List<MarathonListVO> marathonListVOS = geConCompetitionSportsMapper.marathonList(marathonListQuery);
        return new PageInfo<>(marathonListVOS);
    }

    @Override
    public MarathonDetailsVO marathonDetails(String id) {
        MarathonDetailsVO marathonDetailsVO = new MarathonDetailsVO();

        GeConCompetitionSports geConCompetitionSports = geConCompetitionSportsMapper.selectById(id);
        BeanUtils.copyProperties(geConCompetitionSports,marathonDetailsVO);

        //组别
        ArrayList<String> groupsArr = new ArrayList<>();
        List<GeConCompetitionGroup> groups = geConCompetitionGroupMapper.selectList(new LambdaQueryWrapper<GeConCompetitionGroup>().eq(GeConCompetitionGroup::getSportId,id));
        for (GeConCompetitionGroup group : groups) {
            groupsArr.add(group.getName());
        }
        marathonDetailsVO.setGroups(groupsArr);

        //报名人数
        Long num = geConUserCompeteMapper.selectCount(
                new LambdaQueryWrapper<GeConUserCompete>()
                        .eq(GeConUserCompete::getMotionId, id)
                        .eq(GeConUserCompete::getSportsType,"2")
                        .eq(GeConUserCompete::getStatus, "0"));
        marathonDetailsVO.setNum(num);

        if(marathonDetailsVO.getType()!=null){//赛事类型
            marathonDetailsVO.setTypeText(geBaseDictService.getTextByCodeAndValue("type_competition",marathonDetailsVO.getType()));
        }

        return marathonDetailsVO;
    }

//    @Override
//    public List<GeConCompetitionSports> getEndList() {
//        lambdaQuery().
//    }

    public static <T> Consumer<T> getIndex(BiConsumer<T, Integer> consumer) {
        class IndexObject {
            int index;
        }
        IndexObject indexObject = new IndexObject();
        return i -> {
            consumer.accept(i, indexObject.index++);
        };
    }

}
